package com.css.fxfzfxqh.modules.singleIndexRiskZoning.service;

import com.css.fxfzfxqh.base.response.RestResponse;
import com.css.fxfzfxqh.modules.buildingKilometerGrid.threadpool.BizThreadPoolManage;
import com.css.fxfzfxqh.modules.buildings.calculationTasks.entity.CalculationTasks;
import com.css.fxfzfxqh.modules.buildings.calculationTasks.repository.CalculationTasksRepository;
import com.css.fxfzfxqh.modules.buildings.calculationTasks.service.CalculationTasksService;
import com.css.fxfzfxqh.modules.buildings.probabilityEvaluation.casualtiesPE.service.CasualtiesPEService;
import com.css.fxfzfxqh.modules.buildings.probabilityEvaluation.economicLossPE.service.EconomicLossPDService;
import com.css.fxfzfxqh.modules.buildings.probabilityEvaluation.resistEarthquakesPE.service.ResistEarthquakesPEService;
import com.css.fxfzfxqh.modules.singleIndexRiskZoning.model.entity.FxqhAssessPdQhResult;
import com.css.fxfzfxqh.modules.singleIndexRiskZoning.model.vo.FxqhAssessPdQhResultVo;
import com.css.fxfzfxqh.modules.singleIndexRiskZoning.param.QhSingleExportParam;
import com.css.fxfzfxqh.modules.singleIndexRiskZoning.repository.impl.ProbabilityAssessQhRepository;
import com.css.fxfzfxqh.modules.singleIndexRiskZoning.vo.QhSingleExportVO;
import com.css.fxfzfxqh.modules.singleIndicatorRiskZoneSet.service.SingleIndicatorRiskZoneSetService;
import com.css.fxfzfxqh.modules.util.ExcelUtil;
import com.css.fxfzfxqh.modules.util.hypergraph.service.HypergraphService;
import com.css.fxfzfxqh.util.EasyPoiExcelUtil;
import com.css.fxfzfxqh.util.PlatformDateUtils;
import com.css.fxfzfxqh.util.PlatformSessionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Transactional(rollbackFor = Exception.class)
@Service
public class ProbabilityAssessQhService {
    @Autowired
    private CalculationTasksService calculationTasksService;
    @Autowired
    private CalculationTasksRepository calculationTasksRepository;
    @Resource
    private HypergraphService hypergraphService;
    @Autowired
    ProbabilityAssessQhRepository probabilityAssessQhRepository;
    @Resource
    ResistEarthquakesPEService resistEarthquakesPEService;
    @Resource
    CasualtiesPEService casualtiesPEService;
    @Resource
    EconomicLossPDService economicLossPDService;
    @Autowired
    private SingleIndicatorRiskZoneSetService singleIndicatorRiskZoneSetService;

    public RestResponse doZoning(String taskId,String selectedVal) throws Exception{
        RestResponse restResponse = null;
        try {
            List<FxqhAssessPdQhResult> resultList = new ArrayList<>();
            CalculationTasks calculationTasks = calculationTasksService.findById(taskId);
            if (calculationTasks.getAssessType().equals("0")) {
                throw new RuntimeException("当前任务为确定评估，无法进行概率评估风险区划");
            }
            String[] split = selectedVal.split(",");
            probabilityAssessQhRepository.delByTaskId(taskId, Arrays.asList(split));
            //区划评估对象,0:破坏程度;1:人员伤亡;2:经济损失
            String assessObjArrStr = calculationTasks.getAssessObj();
            List<FxqhAssessPdQhResult> tempList = new ArrayList<>();
//            for (String assessObj : assessObjArrStr.split(",")) {
            for (String assessObj : selectedVal.split(",")) {
                //破坏程度
                if ("0".equals(assessObj)) {
                    resultList = resistEarthquakesPEService.doZoning(calculationTasks);
                }
                //人员伤亡
                else if ("1".equals(assessObj)) {
                    resultList = casualtiesPEService.doZoning(calculationTasks);
                }
                //经济损失
                else if ("2".equals(assessObj)) {
                    resultList = economicLossPDService.doZoning(calculationTasks);
                }
                if(resultList.size()>0){
                    for (FxqhAssessPdQhResult result : resultList) {
                        if (result.getEstimateObj() != null) {
                            int type = taskEstimateObjConvertRiskZoneType(result);
                            result.setQhLevel(singleIndicatorRiskZoneSetService.getLevel(result.getCalculatedValue(), type));
                        }
                        probabilityAssessQhRepository.saveFxqhAssessPdResult(result);
                    }
                }
            }
            updateTask(calculationTasks);
            //更新计算进度
            for (String assessObj : assessObjArrStr.split(",")) {
                //破坏程度
                if ("0".equals(assessObj)) {
                    for (String seismicInputMode : calculationTasks.getSeismicInputMode().split(",")) {
                        if (seismicInputMode.equals("0")) {
                            calculationTasksRepository.updateLdProgress(calculationTasks.getId(), "单指标区划", "结构破坏");
                        }
                        if (seismicInputMode.equals("1")) {
                            calculationTasksRepository.updateFourProbabilisticProgress(calculationTasks.getId(), "单指标区划", "结构破坏");
                        }
                        if (seismicInputMode.equals("2")) {
                            calculationTasksRepository.updateStructuralFieldProgress(calculationTasks.getId(), "单指标区划", "结构破坏");
                        }
                    }
                }
                //人员伤亡
                else if ("1".equals(assessObj)) {
                    for (String seismicInputMode : calculationTasks.getSeismicInputMode().split(",")) {
                        if (seismicInputMode.equals("0")) {
                            calculationTasksRepository.updateLdProgress(calculationTasks.getId(), "单指标区划", "人员伤亡");
                        }
                        if (seismicInputMode.equals("1")) {
                            calculationTasksRepository.updateFourProbabilisticProgress(calculationTasks.getId(), "单指标区划", "人员伤亡");
                        }
                        if (seismicInputMode.equals("2")) {
                            calculationTasksRepository.updateStructuralFieldProgress(calculationTasks.getId(), "单指标区划", "人员伤亡");
                        }
                    }
                }
                //经济损失
                else if ("2".equals(assessObj)) {
                    for (String seismicInputMode : calculationTasks.getSeismicInputMode().split(",")) {
                        if (seismicInputMode.equals("0")) {
                            calculationTasksRepository.updateLdProgress(calculationTasks.getId(), "单指标区划", "经济损失");
                        }
                        if (seismicInputMode.equals("1")) {
                            calculationTasksRepository.updateFourProbabilisticProgress(calculationTasks.getId(), "单指标区划", "经济损失");
                        }
                        if (seismicInputMode.equals("2")) {
                            calculationTasksRepository.updateStructuralFieldProgress(calculationTasks.getId(), "单指标区划", "经济损失");
                        }
                    }
                }
            }
            BizThreadPoolManage.exeBizThreadPoolExecutor.execute(() -> {
                //刷新指定超图工作空间数据源数据集
                boolean bool = hypergraphService.getWorkspaceReload("fxqh_assess_pd_qh_result");
            });
            restResponse = RestResponse.succeed();
            restResponse.setMessage("计算成功！");
        } catch (Exception e) {
            e.printStackTrace();
            restResponse = RestResponse.fail(e.getLocalizedMessage());
        }
        return restResponse;
    }

    public List<FxqhAssessPdQhResultVo> getAssessPdQhList(FxqhAssessPdQhResult param) {
        List<FxqhAssessPdQhResult> assessPdQhList = probabilityAssessQhRepository.getAssessPdQhList(param);
        return assessPdQhList.stream().map(o -> {
            FxqhAssessPdQhResultVo vo = new FxqhAssessPdQhResultVo();
            if (o.getCalculatedValue() == null) {
                o.setCalculatedValue(BigDecimal.ZERO);
            }
            BeanUtils.copyProperties(o, vo);
//            vo.setCondition(o.getCondition() + "年");
            vo.setCondition(o.getCondition());
            return vo;
        }).collect(Collectors.toList());
    }

    private static int taskEstimateObjConvertRiskZoneType(FxqhAssessPdQhResult o) {
        int type;
        if (o.getEstimateObj().equals("0")) {
            type = 1;
        } else if (o.getEstimateObj().equals("1")) {
            type = 2;
            if (o.getBorderlandFlag() != null && o.getBorderlandFlag().equals("1")) {
                type = 3;
            }
        } else {
            type = 4;
            if (o.getBorderlandFlag() != null && o.getBorderlandFlag().equals("1")) {
                type = 5;
            }
        }
        return type;
    }

    @Transactional
    public RestResponse updateTask(CalculationTasks entity) {
        String userId = PlatformSessionUtils.getUserId();
        entity.setUpdateUser(userId);
        entity.setUpdateTime(PlatformDateUtils.getCurrentTimestamp());
        calculationTasksService.updateById(entity);
        return RestResponse.succeed("修改成功！");
    }

    public void exportData(HttpServletResponse response, QhSingleExportParam param) {
        List<QhSingleExportVO> qhSingleExportVOS = probabilityAssessQhRepository.getByParam(param);
        // //隐藏经纬度范围字段
        // ArrayList<String> list1 = new ArrayList<>();
        // list1.add("coordinateRange");
        // ExcelUtil.hideColumn(ExportVO.class, list1, true);
        ArrayList<String> list = new ArrayList<>();
        list.add("condition");
        ExcelUtil.hideColumn(QhSingleExportVO.class, list, true);
        // String assessObj = param.getAssessObj();
        try {
            EasyPoiExcelUtil.exportExcel(qhSingleExportVOS, "单指标概率评估风险区划", "风险区划", QhSingleExportVO.class, "单指标概率评估风险区划.xlsx",
                    response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
